package bb.lanxing.activity.sport;

import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.LimitLine;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.ValueFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import com.github.mikephil.charting.utils.Utils;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import bb.lanxing.R;
import bb.lanxing.activity.base.BaseActivity;
import bb.lanxing.model.database.ITrackPoint;
import bb.lanxing.model.database.Workout;
import bb.lanxing.model.json.WorkoutExtraInfo;

public class SportRecordChartActivity extends BaseActivity {
    private static final int[] yText = {R.string.workout_chart_axis_speed, R.string.workout_chart_axis_altitude,
            R.string.workout_chart_axis_heartrate, R.string.workout_chart_axis_cadence,
            R.string.workout_chart_axis_power};
    private static final int[] yText1 = {R.string.workout_detail_tag_speed, R.string.workout_detail_tag_altitude,
            R.string.workout_detail_tag_heartrate, R.string.workout_detail_tag_cadence,
            R.string.workout_detail_tag_power};
    private static final int[] colors = {R.color.color_21d352, R.color.color_11aefa,
            R.color.color_fe4545, R.color.sport_record_cadence_bg3, R.color.purple_500};
    private static final String[] units = {"km/h", "m", "bpm", "rpm", "w"};
    private static final DecimalFormat df = new DecimalFormat("#.##");

    private TextView unit;
    private TextView unitRight;
    private LineChart lineChart;

    private List<Integer> typeList = new ArrayList<>();

    private Workout workout;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sport_record_chart);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        ImageView back = findViewById(R.id.back);
        back.setOnClickListener(v -> onBackPressed());

        List<ToggleButton> toggleButtons = new ArrayList<>();
        ToggleButton speedTV = findViewById(R.id.speed);
        speedTV.setOnCheckedChangeListener((buttonView, isChecked) -> {
            changeTypeList(buttonView, isChecked, 0);
        });
        toggleButtons.add(speedTV);
        ToggleButton altitudeTV = findViewById(R.id.altitude);
        altitudeTV.setOnCheckedChangeListener((buttonView, isChecked) -> {
            changeTypeList(buttonView, isChecked, 1);
        });
        toggleButtons.add(altitudeTV);
        ToggleButton heartrateTV = findViewById(R.id.heartrate);
        heartrateTV.setOnCheckedChangeListener((buttonView, isChecked) -> {
            changeTypeList(buttonView, isChecked, 2);
        });
        toggleButtons.add(heartrateTV);
        ToggleButton cadenceTV = findViewById(R.id.cadence);
        cadenceTV.setOnCheckedChangeListener((buttonView, isChecked) -> {
            changeTypeList(buttonView, isChecked, 3);
        });
        toggleButtons.add(cadenceTV);
        ToggleButton powerTV = findViewById(R.id.power);
        powerTV.setOnCheckedChangeListener((buttonView, isChecked) -> {
            changeTypeList(buttonView, isChecked, 4);
        });
        toggleButtons.add(powerTV);

        unit = findViewById(R.id.unit);
        unitRight = findViewById(R.id.unitRight);

        TextView xValue = findViewById(R.id.xValue);
        TextView yValue = findViewById(R.id.yValue);
        TextView yValue2 = findViewById(R.id.yValue2);

        lineChart = findViewById(R.id.speedChart);
        lineChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
            @Override
            public void onValueSelected(Entry e, Highlight h) {
                xValue.setText(getTimeFormat(e.getX()));
                yValue.setText("");
                yValue2.setText("");
                LineData lineData = lineChart.getData();
                for (int i = 0; i < typeList.size(); i++) {
                    float y = lineData.getDataSetByIndex(i).getEntryForXValue(e.getX(), Float.NaN).getY();
                    if (i == 0) {
                        yValue.setText(getText(yText1[typeList.get(i)]) + ": " + df.format(y) + units[typeList.get(i)]);
                        yValue.setTextColor(getColor(colors[typeList.get(i)]));
                    } else {
                        yValue2.setText(getText(yText1[typeList.get(i)]) + ": " + df.format(y) + units[typeList.get(i)]);
                        yValue2.setTextColor(getColor(colors[typeList.get(i)]));
                    }
                }
            }

            @Override
            public void onNothingSelected() {
            }
        });
        int type = getIntent().getIntExtra("type", 0);
        toggleButtons.get(type).setChecked(true);
        workout = getIntent().getParcelableExtra("workout");
        if (workout.getMaxHeartrate() == 0) {
            heartrateTV.setVisibility(View.GONE);
        }
        if (workout.getMaxCadence() == 0) {
            cadenceTV.setVisibility(View.GONE);
        }
        WorkoutExtraInfo workoutExtraInfo = workout.getWorkoutExtraInfo();
        if (workoutExtraInfo.getMaxPower() <= Utils.DOUBLE_EPSILON) {
            powerTV.setVisibility(View.GONE);
        }
        changeLineChart();
    }

    private void changeTypeList(CompoundButton toggleButton, boolean isChecked, int type) {
        if (isChecked) {
            if (typeList.size() == 2) {
                toggleButton.setChecked(false);
                Toast.makeText(this, "最多只能选择两个", Toast.LENGTH_SHORT).show();
                return;
            }
            toggleButton.setTextColor(getColor(R.color.color_f2));
            typeList.add(type);
        } else {
            toggleButton.setTextColor(getColor(R.color.grey_b2b2b2));
            for (int i = 0; i < typeList.size(); i++) {
                if (typeList.get(i) == type) {
                    typeList.remove(i);
                    break;
                }
            }
        }
        changeLineChart();
    }

    private void changeLineChart() {
        if (workout == null) {
            return;
        }
        List<List<Entry>> entryLists = new ArrayList<>();
        List<Float> maxValues = new ArrayList<>();
        List<Float> avgValues = new ArrayList<>();
        WorkoutExtraInfo workoutExtraInfo = workout.getWorkoutExtraInfo();
        List<ITrackPoint> trackpointList = workout.getTrackPointsForChart();
        if (trackpointList == null) {
            return;
        }
        for (int j = 0; j < typeList.size(); j++) {
            List<Entry> entryList = new ArrayList<>();
            switch (typeList.get(j)) {
                case 0:
                    maxValues.add((float) workout.getMaxSpeed() * 3.6f);
                    float avgSpeed = (float) workout.getDistance() / workout.getDuration() * 3.6f;
                    if ((workout.getSport() == Workout.TYPE_TRAINING)
                            || (workout.getSport() == Workout.TYPE_INDOOR_BIKE)
                            || (workout.getSport() == Workout.TYPE_BIKE_TRAINER)
                            || (workout.getSport() == Workout.TYPE_ROWER)
                            || (workout.getSport() == Workout.TYPE_CROSS_TRAINER)) {
                        avgSpeed = (float) workout.getAvgSpeed() * 3.6f;
                    }
                    avgValues.add(avgSpeed);
                    for (int i = 0; i < trackpointList.size(); i++) {
                        entryList.add(new Entry(trackpointList.get(i).getTime() - trackpointList.get(0).getTime(),
                                (float) trackpointList.get(i).getSpeed() * 3.6f));
                    }
                    break;
                case 1:
                    maxValues.add((float) workoutExtraInfo.getMaxAltitude());
                    avgValues.add((float) workoutExtraInfo.getAvgAltitude());
                    for (int i = 0; i < trackpointList.size(); i++) {
                        entryList.add(new Entry(trackpointList.get(i).getTime() - trackpointList.get(0).getTime(),
                                (float) trackpointList.get(i).getAltitude()));
                    }
                    break;
                case 2:
                    maxValues.add((float) workout.getMaxHeartrate());
                    avgValues.add((float) workout.getAvgHeartrate());
                    for (int i = 0; i < trackpointList.size(); i++) {
                        entryList.add(new Entry(trackpointList.get(i).getTime() - trackpointList.get(0).getTime(),
                                trackpointList.get(i).getHeartrate()));
                    }
                    break;
                case 3:
                    maxValues.add((float) workout.getMaxCadence());
                    avgValues.add((float) workout.getAvgCadence());
                    for (int i = 0; i < trackpointList.size(); i++) {
                        entryList.add(new Entry(trackpointList.get(i).getTime() - trackpointList.get(0).getTime(),
                                trackpointList.get(i).getCadence()));
                    }
                    break;
                case 4:
                    maxValues.add((float) workoutExtraInfo.getMaxPower());
                    avgValues.add((float) workoutExtraInfo.getAvgPower());
                    for (int i = 0; i < trackpointList.size(); i++) {
                        entryList.add(new Entry(trackpointList.get(i).getTime() - trackpointList.get(0).getTime(),
                                (float) trackpointList.get(i).getPower()));
                    }
                    break;
            }
            entryLists.add(entryList);
        }
        boolean[] needFills = {false, true, false, false, false};
        LineData data = new LineData();
        unit.setText("");
        unitRight.setText("");
        lineChart.getAxisLeft().removeAllLimitLines();
        lineChart.getAxisRight().setDrawLabels(false);
        lineChart.getAxisRight().setDrawGridLines(false);
        lineChart.getAxisRight().removeAllLimitLines();
        for (int i = 0; i < entryLists.size(); i++) {
            LineDataSet dataSet = getLineDataSet(entryLists.get(i), getColor(colors[typeList.get(i)]),
                    needFills[typeList.get(i)], getColor(colors[typeList.get(i)]), i);
            data.addDataSet(dataSet);
            YAxis yAxis = lineChart.getAxisLeft();
            if (i == 1) {
                yAxis = lineChart.getAxisRight();
                yAxis.setDrawLabels(true);
                unitRight.setText(yText[typeList.get(i)]);
                unitRight.setTextColor(getColor(colors[typeList.get(i)]));
            } else {
                unit.setText(yText[typeList.get(i)]);
                unit.setTextColor(getColor(colors[typeList.get(i)]));
            }
            setYAxis(yAxis, maxValues.get(i), avgValues.get(i));
        }
        initLineChart(lineChart, data);
        lineChart.invalidate();
    }

    private LineDataSet getLineDataSet(List<Entry> entries, int lineColor, boolean filled, int FillColor, int axisDependency) {
        LineDataSet dataSet = new LineDataSet(entries, "");
        dataSet.setColor(lineColor);
        dataSet.setLineWidth(1.5f);
        dataSet.setDrawCircles(false);
        if (axisDependency == 0) {
            dataSet.setAxisDependency(YAxis.AxisDependency.LEFT);
        } else {
            dataSet.setAxisDependency(YAxis.AxisDependency.RIGHT);
        }
        dataSet.setDrawFilled(filled);
        if (filled) {
            dataSet.setFillColor(FillColor);
        }
        return dataSet;
    }

    private void setYAxis(YAxis yAxis, float maxData, float avgData) {
        yAxis.setTextSize(1f);
        yAxis.setAxisMaximum(maxData * 1.1f);
        yAxis.setAxisMinimum(0);
        yAxis.setDrawGridLines(false);
        yAxis.setLabelCount(5, true);
        LimitLine limitLine = new LimitLine(maxData * 1.1f);
        limitLine.enableDashedLine(10, 10, 0);
        limitLine.setLineColor(Color.GRAY);
        yAxis.addLimitLine(limitLine);
        LimitLine limitLine1 = new LimitLine(avgData);
        limitLine1.enableDashedLine(10, 10, 0);
        limitLine1.setLineWidth(1.5f);
        yAxis.addLimitLine(limitLine1);
    }

    private void initLineChart(LineChart chart, LineData data) {
        chart.setData(data);
        chart.setDescription(null);
        chart.getLegend().setEnabled(false);
        chart.setScaleYEnabled(false);
        XAxis xAxis = chart.getXAxis();
        xAxis.setTextSize(1f);
        xAxis.setDrawGridLines(false);
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setLabelCount(7, true);
        xAxis.setValueFormatter(new ValueFormatter() {
            @Override
            public String getFormattedValue(float value) {
                return getTimeFormat(value);
            }
        });
    }

    private String getTimeFormat(float value) {
        long totalSeconds = (long) (value / 1000);
        long totalMinutes = totalSeconds / 60;
        long totalHours = totalMinutes / 60;
        long seconds = totalSeconds % 60;
        long minutes = totalMinutes % 60;
        long hours = totalHours;
        return String.format("%02d:%02d:%02d", hours, minutes, seconds);
    }
}